<?php
/**
 * FileName: CategoryService.php
 * Author: Fei.Song
 * Date: 2021/5/25 23:09
 * Created by PhpStorm
 * Desc:
 */

namespace App\Service;

use App\Lib\ChineseFirstCharter;
use App\Lib\Enum\ValRule;
use App\Lib\Logger;
use App\Models\Category;
use App\Models\CategoryGroup;
use App\Models\CategoryTagGroup;
use App\Rules\CheckRule;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;

class CategoryService extends BaseService {
    protected $modelName="Category";
    /**
     * @var string 站点栏目设置缓存KEY
     */
    protected $cachePrefix = 'Cat_';

    /**
     * @var float|int 缓存有效期
     */
    protected $ttl = 60 * 60 * 24 * 5;//5天

    /**
     * @var array[] 类别分组,等同category_group表数据,必要时修改
     */
    protected $categoryGroup = [
        1 => ['id' => 1, 'code' => 'course', 'name' => '课程', 'depth' => 4],
        2 => ['id' => 2, 'code' => 'classroom', 'name' => '班级', 'depth' => 2],
        3 => ['id' => 3, 'code' => 'offlineActivity', 'name' => '线下活动', 'depth' => 2],
    ];

    /**
     * 新增分类
     * @param $cat
     * @return mixed
     */
    public function add($cat) {
        $cat = (new Category())->create($cat)->toArray();
        $this->log(Logger::LOG_LEVEL_INFO, Logger::CATEGORY, 'create', "新增栏目分类[ID:" . $cat['id'] . "],成功", $cat);
        return $cat;
    }

    /**
     * 新增分类带更新路径
     * @param $cat 添加的待处理参数
     * @author 郭碧云
     */
    public function addAndPath($cat) {
        $cat = (new Category())->create($cat)->toArray();
        //更新全路径
        $this->upDepth($cat);
        $this->log(Logger::LOG_LEVEL_INFO, Logger::CATEGORY, 'create', "新增栏目分类[ID:" . $cat['id'] . "],成功", $cat);
        return $cat;
    }


    /**
     * 编辑分类
     * @param $id
     * @param $cat
     * @return mixed
     */
    public function update($id, $cat) {
        $cat = Category::where("id", $id)->update($cat);
        $this->log(Logger::LOG_LEVEL_INFO, Logger::CATEGORY, 'update', "修改分类[ID:{$id}],成功", $cat);
        return $cat;
    }

    /**
     * 更新深度，路径
     */
    public function upDepth($cat){
        //更新全路径
        if ($cat["parent_id"] == 0) {
            $path = $cat["id"] . ".";
            $depth = 1;
        } else {
            //获取父类路径，合成当前分类路径
            $father = (new Category())->whereBuilder(["id" => $cat["parent_id"]])->first()->toArray();
            $path = $father["path"] . $cat["id"] . ".";
            $depth = count(explode(".", $path)) - 1;
        }
        $this->update($cat["id"], ["path" => $path, "depth" => $depth]);
    }

    /**
     * 按照站点ID获取分类列表
     * @param int $groupId 分类ID
     * @param int $siteId 站点ID
     * @return mixed
     */
    public function getCategoryList($groupId, $siteId = 0) {
        $where['group_id'] = $groupId;
        if (!getCurrentSiteId() && $siteId) {
            $where['site_id'] = $siteId;
        }
        return $this->getCategoryAll($where);
    }

    /**
     * 通过缓存按照分类组读取分类列表
     * @param $groupId
     * @return mixed
     */
    public function getCategoryByGroupId($groupId) {
        $category = Cache::get($this->cacheKey($groupId));
        if (!$category) {
            $category = $this->cache($groupId);
        }
        return $category;
    }

    /**
     * 按条件查询数据
     * @param array $where
     * @return mixed
     */
    private function getCategoryAll($where = []) {
        return (new Category())->whereBuilder($where)->orderBy('sort', 'asc')->get()->toArray();
    }

    /**
     * 根据ID查询分类
     * @param $id
     * @return array | null
     */
    public function getCategoryById($id) {
        $cat = Category::find($id);
        if ($cat) {
            return $cat->toArray();
        }
        return null;
    }

    /**
     * 生成缓存KEY
     * @param int $groupId 分类分组ID
     * @param int $siteId 站点ID
     * @return string
     */
    private function cacheKey($groupId, $siteId = 0) {
        if (!getCurrentSiteId() && $siteId) {
            $siteId = ['site_id', '=', $siteId];
        } else {
            $siteId = getCurrentSiteId();
        }
        return $this->cachePrefix . $groupId . "_" . $siteId;
    }

    /**
     * @param int $groupId
     * @param int $siteId
     * @return mixed
     */
    public function cache($groupId = 0, $siteId = 0) {
        if (!getCurrentSiteId() && $siteId) {
            $where['site_id'] = $siteId;
        }
        $where['status'] = 1;
        if ($groupId) {
            $where['group_id'] = $groupId;
            $category = $this->getCategoryAll($where);
            if ($category) {
                $cacheKey = $this->cacheKey($groupId, $siteId);
                Cache::put($cacheKey, $category, $this->ttl);
                return $category;
            }
        } else {
            if ($where['site_id']) {
                $categoryGroup = $this->getCategoryGroupList();
                foreach ($categoryGroup as $groupId => $group) {
                    $where['group_id'] = $groupId;
                    $category = $this->getCategoryAll($where);
                    $cacheKey = $this->cacheKey($groupId, $siteId);
                    Cache::put($cacheKey, $category, $this->ttl);
                }
            } else {
                return null;
            }
        }
    }

    /**
     * 获取分类的标签组
     * @param $catId 分类ID
     * @param $tagType 标签组类别 'course','exam'
     * @return mixed
     */
    public function getTagGroupByCategory($catId, $tagType = 'course') {
        $category = (new Category())->firstWhere('id', $catId);
        $tagType = $tagType . 'TagGroup';
        return $category->$tagType;
    }

    /**
     * 获取分类组列表
     * @return array[]
     */
    public function getCategoryGroupList() {
        return $this->categoryGroup;
    }

    /**
     * 按照groupId获取分类组
     * @param $groupId
     * @return array
     */
    public function getCategoryGroupByGroupId($groupId) {
        return $this->categoryGroup[$groupId];
    }

    /**
     * 删除
     * @param $id
     * @return boolean
     */
    public function delete($id) {
        return (new Category())->where("id", $id)->delete();
    }

    /**
     * 添加标签
     * 备注：旧标签如果存在，则删除后添加
     */
    public function addTags($category_id, $params) {
        $data = [];
        //获取插入数据
        $course = explode(",", $params["course"]);
        foreach ($course as $k => $tag) {
            $data[$k]["category_id"] = $category_id;
            $data[$k]["tag_type"] = "course";
            $data[$k]["tag_group_id"] = $tag;
            $data[$k]["created_at"] = time();
            $data[$k]["updated_at"] = time();
        }
        $exam = ["category_id" => $category_id, "tag_type" => "exam", "tag_group_id" => $params["exam"], "created_at" => time(), "udpated_at" => time()];
        array_push($data, $exam);
        //检查数据是否存在
        $hasExam = (new CategoryTagGroup())->where("category_id", $category_id)->get();
        if (!empty($hasExam)) {
            (new CategoryTagGroup())->where("category_id", $category_id)->delete();
        }
        return (new CategoryTagGroup())->insertOrIgnore($data);
    }

    /**
     * 获取展示数据
     * @param $id 分类id
     * @author 郭碧云
     */
    public function getShowInfo($id) {
        $data = $this->getCategoryById($id);
        $group = $this->getCategoryGroupByGroupId($data["group_id"]);
        $data["group_name"] = $group["name"];
        if ($data["parent_id"] == 0) {
            $data["parent_name"] = "顶级";
        } else {
            $parent = $this->getCategoryById($data["parent_id"]);
            $data["parent_name"] = $parent["name"];
        }
        return $data;
    }

    /**
     * 排序
     * @author 郭碧云
     */
    public function setSort($id, $sort) {
        return (new Category())->where("id", $id)->update(["sort" => $sort]);
    }

    /**
     * 按照站点ID获取分类列表，带子集个数
     * @param int $groupId 分类ID
     * @param int $siteId 站点ID
     * @return array
     * @author 郭碧云
     */
    public function getCategoryList2($groupId, $siteId = 0) {
        $where['group_id'] = $groupId;
        if (!getCurrentSiteId() && $siteId) {
            $where['site_id'] = $siteId;
        }
        $data = $this->getUserCategory($where);
        $data = $this->addStatusDom($data, $groupId);
        return $data;
    }

    /**
     * 获取该用户下的科目分类
     * @param $where 条件数组
     * @param $isSite 1表示是管理员，0表示不是
     * @param $categories 用户拥有的科目id字符串
     * @author 郭碧云
     */
    public function getUserCategory($where, $isSite = 1, $categories = []) {
        if (getCurrentSiteId() == 0 || !empty($isSite)) {
            $data = $this->getCategoryAll($where);
        } else {
            $data = (new Category())->whereBuilder($where)->whereIn("id", $categories)->orderBy("sort", "asc")->get()->toArray();
        }
        return $data;
    }

    /**
     * 判断层级深度
     * @param $data 分类数组
     * @author 郭碧云
     */
    private function addStatusDom($data, $groupId) {
        if (!empty($data)) {
            //获取添加深度
            $depth = (new CategoryGroup())->whereBuilder(["id" => $groupId])->first()->toArray();
            foreach ($data as $k => $v) {
                $data[$k]["depth"] < $depth["depth"] ? $data[$k]["addStatus"] = true : $data[$k]["addStatus"] = false;
            }
        }
        return $data;
    }

    /**
     * 获取更新数据
     * @param $params 获取数据
     * @param $type 类型 0 表示创建，1表示更新
     * @author 郭碧云
     */
    public function getCData($params, $type = 0) {
        //参数验证
        $type == 0 ? $params["data"]['site_id'] = getCurrentSiteId() : $params["data"]["id"] = $params["id"];
        $params = (new CheckRule($params["data"], ValRule::CATEGORY, ValRule::CATEGORY_MSG))->check();
        if ($params["error"] > 0) {
            return ["error" => $params['error'], "msg" => $params['msg']];
        }
        //同一级别下，名称不可以相同
        $isExit = (new Category())->whereBuilder(["name" => $params["data"]["name"], "parent_id" => $params["data"]["parent_id"]])->first();
        if ((!empty($isExit)&&$type==0)||(!empty($isExit)&&$type==1&&$isExit["id"]!=$params["data"]["id"])) {
            return ["error" => 70002, "msg" => "该分类下已存在科目"];
        }

        //处理描述为空
        if (array_key_exists("description", $params["data"]) && ($params["data"]["description"] == null || empty($params["data"]["description"]))) {
            $params["data"]["description"] = "";
        }
        if ($params["data"]["group_id"] == 1) {
            if (!array_key_exists("scope", $params["data"])) {
                return ["error" => 9000, "msg" => "请输入适用范围"];
            }
            $params["data"]["scope_course"] = in_array("course", $params["data"]["scope"]) ? 1 : 0;
            $params["data"]["scope_exam"] = in_array("exam", $params["data"]["scope"]) ? 1 : 0;
        }

        //中文转首拼
        $params["data"]["code"] = $this->getCode($params["data"]["name"]);
        unset($params["data"]["scope"]);
        return $params;
    }

    /**
     * code中文转拼音首拼
     * @param $name 中文名称
     * @author 郭碧云
     */
    private function getCode($name) {
        $code = (new ChineseFirstCharter())->getFirstCharters($name);
        //排重
        $isHas = (new Category())->where("code", $code)->first();
        if (!empty($isHas)) {
            $code = $code . Str::random(2);
        }
        return $code;
    }
}
